package com.mytx.sso.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mytx.common.constant.Const;
import com.mytx.common.constant.Constant;
import com.mytx.common.pojo.CommonResult;
import com.mytx.common.pojo.RedisLock;
import com.mytx.common.utils.IDUtils;
import com.mytx.mapper.CoinTransferMapper;
import com.mytx.mapper.UserMapper;
import com.mytx.pojo.CoinTransfer;
import com.mytx.pojo.CoinTransferExample;
import com.mytx.pojo.Transfer;
import com.mytx.pojo.User;
import com.mytx.sso.utils.PayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@RestController
public class TransferController {
    private static Logger logger = LoggerFactory.getLogger(TransferController.class);


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    UserMapper userMapper;

    @Autowired
    CoinTransferMapper coinTransferMapper;

    @PostMapping("/coinTransfer")
    @Transactional
    public CommonResult coinTransfer(@RequestBody JSONObject body) {
        String uId = request.getHeader("uId");
        RedisLock lock = new RedisLock(redisTemplate, Constant.USER_SESSION_LOCK + uId);
        CoinTransfer transfer = body.getObject("coinTransfer", CoinTransfer.class);
        BigDecimal amount = transfer.getAmount();
        String payPassword = body.getString("payPassword");
        User user = getUser(uId);
        try {
            if (!lock.lock()) {
                logger.error("转账，获取锁失败了,uId:{}", uId);
                return CommonResult.build(Constant.GET_LOCK_FAIL, "转账，获取锁失败了");
            }
            CommonResult commonResult = PayUtils.payPrepare(payPassword, amount, user);
            if (commonResult != null) {
                return commonResult;
            }
            transfer.setId(IDUtils.genOrderItemId());
            transfer.setuId(uId);
            coinTransferMapper.insertSelective(transfer);
            BigDecimal myBalance = userMapper.reduceBalance(uId, amount);
            String tUid = transfer.gettId();
            BigDecimal targetUserBalance = userMapper.incrementBalance(tUid, amount);
            //更新双方缓存余额
            redisTemplate.opsForHash().put(Constant.USER_SESSION + uId, Constant.BALANCE, myBalance);
            redisTemplate.opsForHash().put(Constant.USER_SESSION + tUid, Constant.BALANCE, targetUserBalance);
            logger.info("coinTransfer:转账 用户余额减少，uId:{},amount:{},balance:{}", uId, amount, myBalance);
            logger.info("coinTransfer:转账 用户余额增加，uId:{},amount:{},balance:{}", tUid, amount, targetUserBalance);

            JSONObject result = new JSONObject();
            result.put("balance", myBalance);
            result.put("coinTransferId", transfer.getId());
            return CommonResult.ok(myBalance);

        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.error("转账出错：未知错误+message:{}", e.getMessage());
            return CommonResult.build(Constant.UNKNOWN_ERROR, "未知错误");
        } finally {
            lock.unlock();
        }

    }

    @PostMapping("/queryTransfer")
    public CommonResult queryTransfer(@RequestBody JSONObject body) {
        String uId = request.getHeader("uId");
        int page = 1;
        int size = 10;
        if (body.containsKey("page")) {
            page = (int) body.get("page");
        }
        if (body.containsKey("size")) {
            size = (int) body.get("size");
        }

        PageHelper.startPage(page, size);
        List<CoinTransfer> fundCoupons = coinTransferMapper.selectMyTransfer(uId);
        PageInfo pageInfo = new PageInfo<>(fundCoupons);
        return CommonResult.ok(pageInfo);
    }


    private User getUser(String uId) {
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(Constant.USER_SESSION + uId);
        if(entries.isEmpty()){
            return  userMapper.selectByPrimaryKey(uId);
        }
        return JSONObject.parseObject(JSONObject.toJSONString(entries), User.class);
    }
}
